<?php
class cache {

	/**
	 * @author [Seb Skuse]
	 * @copyright 2010
	 */	

	private $resource;
	private $cacheType;
	private $filename;
	private $interval; // in minutes
	private $data;
	protected $db;

	public function __construct($resource, $cacheType, $interval = 30){
		$this->resource = strtolower($resource);
		
		// Is this resource a file, or an object?
		
		$this->filename = SYS_CACHEDIR . $this->resource;
		$this->interval = $interval;
		$this->cacheType = $cacheType;
		$this->db = db::singleton();
	}
	
	public function queryDatabase(){
		$cacheQuery = $this->db->prepare("SELECT UNIX_TIMESTAMP(time) AS time, MD5(originalURL) AS hash, object FROM " . SYS_DB_DBNAME . "." . SYS_DB_PREFIX . $this->db->real_escape_string($this->cacheType) . "_cache WHERE originalURL=?");
		$cacheQuery->bind_param('s', $this->db->real_escape_string($this->resource));
		$cacheQuery->execute();
		$cacheQuery->store_result();
		
		if($cacheQuery->num_rows == 1){

			$cacheQuery->bind_result($time, $hash, $object);
			$cacheQuery->fetch();
			
			$this->data = stripslashes($object);
			
			if( strtotime("+ " . $this->interval . " minutes", $time) < time() ){
				// Data is old, update!
				return array("status" => "EXPIRED");
			} else {
				return array("status" => "OK", "data" => $this->data);
			}
		
		} else {
			return array("status" => "EXPIRED");
		}
		
		$cacheQuery->free_result();
		$cacheQuery->close();
	}
	
	public function queryFile(){
		if(file_exists($this->filename) == true){
			// filemtime() it so we can get the file modified time.
			$fInfo = filemtime($this->filename);
			
			if( $fInfo != null && ( strtotime("+ " . $this->interval . " minutes", $fInfo) < time() ) ) {
				// Data is old, update!
				return array("status" => "EXPIRED");
			} else {
				return array("status" => "OK", "data" => $this->getFile() );
			}
		} else {
			// Make a new file ready to recieve new data.
			return array("status" => "EXPIRED");
		}
	}
	
	public function set($data){
		
		// Replace newlines in the input data.
		$data = str_replace(array("\r\n", "\n", "\r"), "", $data);
		
		// Check to see if the record exists.
		$existCheck = $this->db->oneRow("SELECT COUNT(*) AS recordExists FROM " . SYS_DB_DBNAME . "." . SYS_DB_PREFIX . $this->db->real_escape_string($this->cacheType) . "_cache WHERE originalURL=\"" . $this->db->real_escape_string($this->resource) . "\"" );
		
		if($existCheck['recordExists'] == 1){
			switch($this->cacheType){
				case "object":
					$cacheQuery = $this->db->prepare("UPDATE " . SYS_DB_DBNAME . "." . SYS_DB_PREFIX . $this->db->real_escape_string($this->cacheType) . "_cache SET time=CURRENT_TIMESTAMP(), object=? WHERE originalURL=?");
					$cacheQuery->bind_param('ss', $this->db->real_escape_string($data), $this->resource);
					if($cacheQuery->execute() == false) throw new PicBoardException("MySQL update failed: " . $cacheQuery->error);
					$cacheQuery->close();
				break;
				
				case "image":
					// not implemented
				break;
				
				default:
					throw new PicBoardException("No cachetype specified, cannot set data.");
				break;
			
			}
		} else {
			// Record does not exist. Use an insert.
			
			switch($this->cacheType){
				case "object":
					$cacheQuery = $this->db->prepare("INSERT INTO " . SYS_DB_DBNAME . "." . SYS_DB_PREFIX . $this->db->real_escape_string($this->cacheType) . "_cache (time, object, originalURL) VALUES(CURRENT_TIMESTAMP(), ?, ?)");
					$cacheQuery->bind_param('ss', $this->db->real_escape_string($data), $this->resource);
					if($cacheQuery->execute() == false) throw new PicBoardException("MySQL insert failed: " . $cacheQuery->error);		
					$cacheQuery->close();		
				break;
				
				case "image":
					// not implemented
				break;
				
				default:
					throw new PicBoardException("No cachetype specified, cannot set data.");
				break;
			}
			
		}
		
	}
	
	public function write($data){
		if( is_writable($this->filename) ){
			file_put_contents($this->filename, $data);
		} else {
			throw new PicBoardException("Unable to write file to cache directory.");
		}
	}
	
	private function get(){
		return $this->data;
	}
	
	private function getFile(){
		// This only works at the moment for file based caches.
		if(file_exists($this->resource) == true) return file_get_contents($this->resource);
	}	

}

?>